/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** *****************************************************************************************************
 * \file     Pwm_Ip_Xtrg.c                                                                              *
 * \brief    AUTOSAR 4.3.1 MCAL PWM Driver                                                              *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2024/02/20     <td>3.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif

/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "Pwm_Ip.h"
#include "Pwm_Ip_Xtrg.h"
#include "Pwm_Fault.h"
#include "SchM_Pwm.h"

#define PWM_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Pwm_MemMap.h"

/********************************************************************************************************
 *                                  Global Variable Declarations                                        *
 *******************************************************************************************************/

#define PWM_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Pwm_MemMap.h"

#define PWM_START_SEC_CONST_UNSPECIFIED
#include "Pwm_MemMap.h"
/* XTRG base address list *//* PRQA S 3218 1 */
static const uint32 Pwm_XtrgBaseAddr[PMW_IP_XTRG_MODULE_MAX_NUMBER] =
{ PWM_IP_XTRG1_BASE, PWM_IP_XTRG2_BASE };

/* Xtrg-Pwm counter interval list */
static const uint32 Pwm_XtrgCntIntvList[PWM_IP_XTRG_COUNTER_INTV_NUM] =
{ 1UL, 4UL, 16UL, 64UL, 256UL, 1000UL, 4000UL, 16000UL};

#define PWM_STOP_SEC_CONST_UNSPECIFIED
#include "Pwm_MemMap.h"

#define PWM_START_SEC_CODE
#include "Pwm_MemMap.h"

/********************************************************************************************************
 *                                  Global Function Declarations                                        *
 *******************************************************************************************************/

/** *****************************************************************************************************
 * \brief Assignment Pwm_Handler base address of Xtrg-Pwm registers.
 *
 * \verbatim
 * Syntax             : void Pwm_Ip_XtrgSetBaseAddr(
 *                          Pwm_HandlerConfigType* coreHandlerPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : coreHandlerPtr - Pwm handler configutations.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Assignment Pwm_Handler base address of Xtrg-Pwm registers.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_025
 *******************************************************************************************************/
void Pwm_Ip_XtrgSetBaseAddr(Pwm_HandlerConfigType* coreHandlerPtr)
{
    /* ----- Implementation ----------------------------------------------- */
    /* #10 Set XTRGs base addresses */
    coreHandlerPtr->baseAddr[8] = Pwm_XtrgBaseAddr[0];
    coreHandlerPtr->baseAddr[9] = Pwm_XtrgBaseAddr[1];
}

#if ((STD_ON == PWM_SET_DUTY_CYCLE_API) || (STD_ON == PWM_SET_PERIOD_AND_DUTY_API)          \
    || (STD_ON == PWM_SET_OUTPUT_TO_IDLE_API) || (STD_ON == PWM_NOTIFICATION_SUPPORTED))
/** *****************************************************************************************************
 * \brief Get the hardware module ID, channel ID and sub channel ID.
 *
 * \verbatim
 * Syntax             : static void Pwm_Ip_XtrgGetHardwareChannel(
 *                          Pwm_ChannelType channelNumber,
 *                          Pwm_ModuleType* curModuleIdPtr,
 *                          Pwm_ChannelType* curChannelIdPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : channelNumber - Numeric identifier of the PWM.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : curModuleIdPtr      - Point to numeric identifier of the PWM hardware module.
 *                      curChannelIdPtr     - Point to numeric identifier of the PWM hardware channel.
 *                      curSubChannelIdPtr  - Point to numeric identifier of the PWM hardware sub
 *                                            channel.
 *
 * Return value       : None
 *
 * Description        : Get the hardware module ID, channel ID and sub channel ID.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007
 *******************************************************************************************************/
static void Pwm_Ip_XtrgGetHardwareChannel
(
    Pwm_ChannelType channelNumber,
    Pwm_ModuleType* curModuleIdPtr,
    Pwm_ChannelType* curChannelIdPtr
)
{
    /* ----- Local Variables ---------------------------------------------- */
    boolean channelFound = (boolean)FALSE;
    Pwm_ModuleType moduleNum;
    Pwm_ChannelType channelNum;
    Pwm_ChannelType subChannelNum;
    Pwm_ModuleType curModule;
    Pwm_ChannelType curChannel;
    Pwm_ChannelType curSubChannel;
    Pwm_ChannelType logicChannel = 0U;

    /* #10 Get core id and pwm handler */
    uint8 coreId = Pwm_Ip_GetCoreID();
    Pwm_HandlerConfigType const* coreHandlerPtr = Pwm_HandlerPtr[coreId];
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;
    const Pwm_ConfigType* configPtr = coreHandlerPtr->configPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* #20 Get pwm moudle total number */
    moduleNum = configPtr->moduleNum;
    /* #30 Loop all modules and channels to find the right channel */
    for (curModule = ((uint8)0U);  curModule < moduleNum;  curModule++)
    {
        moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
        channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
        /* Get the channel number */
        channelNum = moduleCfgPtr->channelNum;
        /* #40 Loop channels to find the rigth channel */
        for (curChannel = ((uint8)0U); curChannel < channelNum; curChannel++)
        {
            /* Get the subchannel number */
            if ((boolean)TRUE == channelGroupCfgPtr->channelGroup[curChannel].bothCmpOutput)
            {
                subChannelNum = 2;
            }
            else
            {
                subChannelNum = 1;
            }
            /* #50 Loop subchannels to find the rigth channel */
            for (curSubChannel = ((uint8)0U); curSubChannel < subChannelNum; curSubChannel++)
            {
                logicChannel++;
                if (channelNumber == logicChannel)
                {
                    /* Out point parameters assignment */
                    *curModuleIdPtr = curModule;
                    *curChannelIdPtr = curChannel;
                    /* Find the right chanel, break */
                    channelFound = (boolean)TRUE;
                    break;
                } /* else not needed */
            }
            /* Find the right chanel, break */
            if ((boolean)TRUE == channelFound)
            {
                break;
            } /* else not needed */
        }
        /* Find the right chanel, break */
        if ((boolean)TRUE == channelFound)
        {
            break;
        } /* else not needed */
    }
}
#endif /** #if ((STD_ON == PWM_SET_DUTY_CYCLE_API) || (STD_ON == PWM_SET_PERIOD_AND_DUTY_API)           \
                || (STD_ON == PWM_SET_OUTPUT_TO_IDLE_API) || (STD_ON == PWM_NOTIFICATION_SUPPORTED) */

#define PWM_STOP_SEC_CODE
#include "Pwm_MemMap.h"

#define PWM_START_SEC_CODE_FAST
#include "Pwm_MemMap.h"

/** *****************************************************************************************************
 * \brief Clear the interrupt status of Xtrg-Pwm controller.
 *
 * \verbatim
 * Syntax             : static void Pwm_Ip_Xtrg_ClearIntStatus(
 *                          uint32 base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base - Xtrg-Pwm controller baseAddress.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Clear the interrupt status of Xtrg-Pwm controller.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007 SWSR_PWM_026
 *******************************************************************************************************/
static void Pwm_Ip_Xtrg_ClearIntStatus(uint32 base)
{
    /* ----- Local Variables ---------------------------------------------- */
    uint32 intStatus;

    /* ----- Implementation ----------------------------------------------- */
    SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_00();
    /* #10 Read out the interrupt status */
    intStatus = REG_READ32(base + PWM_IP_XTRG_OVF_INT_STA_REG);
    /* #20 Clear out the interrupt status */
    REG_WRITE32(intStatus, base + PWM_IP_XTRG_OVF_INT_STA_REG);
    SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_00();
}

#define PWM_STOP_SEC_CODE_FAST
#include "Pwm_MemMap.h"

#define PWM_START_SEC_CODE
#include "Pwm_MemMap.h"

/** *****************************************************************************************************
 * \brief Get the appropriate counter interval.
 *
 * \verbatim
 * Syntax             : static uint32 Pwm_Ip_XtrgFindClkIntv(
 *                          uint32 clkIntvValue)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : clkIntvValue    - The calculated interval.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Xtrg-Pwm counter appropriate interval select.
 *
 * Description        : Get the appropriate counter interval.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_026 SWSR_PWM_094
 *******************************************************************************************************/
static uint32 Pwm_Ip_XtrgFindClkIntv(uint32 clkIntvValue)
{
    /* ----- Local Variables ---------------------------------------------- */
    uint32 i;
    uint32 intv_index = PWM_IP_XTRG_COUNTER_INTV_NUM - 1UL;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Find the appropriate interval value */
    for (i = 0; i < PWM_IP_XTRG_COUNTER_INTV_NUM; i++)
    {
        if (clkIntvValue <= Pwm_XtrgCntIntvList[i])
        {
            intv_index = i;
            break;
        } /* else not needed */
    }

    return intv_index;
}

/** *****************************************************************************************************
 * \brief Read the counter interval from the register.
 *
 * \verbatim
 * Syntax             : static uint32 Pwm_Ip_Xtrg_GetClkIntv(
 *                          uint32 base
 *                          const uint8 channelId)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base        - Xtrg-Pwm controller baseAddress.
 *                      channelId   - Index of Xtrg-Pwm channel.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : Read the counter interval from the register.
 *
 * Description        : The counter interval of the register.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_015 SWSR_PWM_026 SWSR_PWM_045
 *******************************************************************************************************/
static uint32 Pwm_Ip_Xtrg_GetClkIntv(uint32 base, const uint8 channelId)
{
    /* ----- Local Variables ---------------------------------------------- */
    uint32 tempValue;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Read out pwm channel configure */
    tempValue = REG_READ32(base + PWM_IP_XTRG_CH_CFG_N(channelId));
    tempValue = (tempValue >> PWM_IP_XTRG_CNT_INTV_SEL_OFFSET) & PWM_IP_XTRG_CNT_INTV_SEL_MASK;

    return tempValue;
}

/** *****************************************************************************************************
 * \brief Select Xtrg-Pwm counter interval.
 *
 * \verbatim
 * Syntax             : static void Pwm_Ip_Xtrg_SetClkIntv(
 *                          uint32 base,
 *                          const uint8 channelId,
 *                          uint32 sel)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base        - Xtrg-Pwm controller baseAddress.
 *                      channelId   - Index of Xtrg-Pwm channel.
 *                      sel         - Counter interval select.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Select Xtrg-Pwm counter interval.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_026 SWSR_PWM_094
 *******************************************************************************************************/
static void Pwm_Ip_Xtrg_SetClkIntv(uint32 base, const uint8 channelId, uint32 sel)
{
    /* ----- Local Variables ---------------------------------------------- */
    uint32 tempValue;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Read out pwm channel configure */
    tempValue = REG_READ32(base + PWM_IP_XTRG_CH_CFG_N(channelId));
    tempValue = tempValue & (~(PWM_IP_XTRG_CNT_INTV_SEL_MASK << PWM_IP_XTRG_CNT_INTV_SEL_OFFSET));
    tempValue |= (sel << PWM_IP_XTRG_CNT_INTV_SEL_OFFSET);
    /* #20 Write out pwm channel configure */
    PWM_REG_WRITE32_RBC(tempValue, (base + PWM_IP_XTRG_CH_CFG_N(channelId)));
}

/** *****************************************************************************************************
 * \brief Set Xtrg-Pwm counter overflow value.
 *
 * \verbatim
 * Syntax             : static Std_ReturnType Pwm_Ip_XtrgSetOverflow(
 *                          Pwm_HandlerConfigType* coreHandlerPtr,
 *                          const Pwm_ModuleType curModule,
 *                          const uint8 channelId,
 *                          const Pwm_PeriodType period)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      curModule       - Numeric identifier of the PWM hardware module.
 *                      channelId       - Index of Xtrg-Pwm channel.
 *                      period          - The period of the PWM channel.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK                          - Set overflow successful.
 *                      PWM_E_COUNTER_OUT_OF_RANGE    - Set overflow failed, counter out of range.
 *
 * Description        : Set Xtrg-Pwm counter overflow value.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_026 SWSR_PWM_094
 *******************************************************************************************************/
static Std_ReturnType Pwm_Ip_XtrgSetOverflow
(
    Pwm_HandlerConfigType* coreHandlerPtr,
    const Pwm_ModuleType curModule,
    const uint8 channelId,
    const Pwm_PeriodType period
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId = E_OK;
    uint16 dividerNum;
    uint32 moduleClk;
    uint64 counterValue = 0;
    Pwm_HrdControllerType moduleId;
    uint32 tempAddr;
    uint32 tempValue;
    uint32 clkIntvReg;
    uint32 clkIntvCfg;
    uint64 clkIntvValue = 0;
    uint32 clkIntvRemainder;
    uint32 xtrgIndex;

    /* #10 Get core id and pwm handler */
    const Pwm_HwModuleConfigType* moduleHwCfgPtr;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ConfigType* configPtr = coreHandlerPtr->configPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* #20 Get module id and module configure */
    moduleHwCfgPtr = &(configPtr->moduleHwCfgPtr[curModule]);
    moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
    moduleId = moduleCfgPtr->moduleId;
    xtrgIndex = (uint32)moduleId - (uint32)XTRG1_MODULE_INDEX;

    /* #30 Get module clock and divider */
    /* ovf = period*clk/divider, EBTresos make sure the OVFValue less than 0xFFFF */
    dividerNum = moduleHwCfgPtr->dividerNum;
    moduleClk = moduleHwCfgPtr->moduleClk;
    clkIntvReg = Pwm_Ip_Xtrg_GetClkIntv(coreHandlerPtr->baseAddr[moduleId], channelId);

    if (period > 0U)
    {
        /* #40 Calculated the counter overflow value */
        counterValue = ((uint64)moduleClk / 1000000UL * period / ((uint64)dividerNum + 1UL)
                / 1000UL);
        clkIntvRemainder = (uint32)(counterValue % (PWM_IP_XTRG_COUNTER_VALUE_MAX + 1UL));
        clkIntvValue = (uint32)(counterValue / (PWM_IP_XTRG_COUNTER_VALUE_MAX + 1UL));
        if (clkIntvRemainder > 0UL)
        {
            clkIntvValue += 1UL;
        } /* else not needed */
    } /* else not needed */

    PwmHook_Pwm_Ip_XtrgSetOverflow();
    /* #50 Check overflow value */
    if (((uint32)clkIntvValue) > PWM_IP_XTRG_COUNTER_INTV_MAX)
    {
        errorId = PWM_E_COUNTER_OUT_OF_RANGE;
    }
    else
    {
        clkIntvCfg = Pwm_Ip_XtrgFindClkIntv((uint32)clkIntvValue);
        if (clkIntvReg != clkIntvCfg)
        {
            tempAddr = coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CNT_EN_REG;
            /* Read out counter enable bits */
            tempValue = REG_READ32(tempAddr);
            if ((tempValue & PWM_IP_XTRG_CNT_EN_CH(channelId)) > 0UL)
            {
                /* Xtrg-Pwm counter disable */
                PWM_REG_WRITE32_RBC((tempValue & (~PWM_IP_XTRG_CNT_EN_CH(channelId))), tempAddr);
            } /* else not needed */
            Pwm_Ip_Xtrg_SetClkIntv(coreHandlerPtr->baseAddr[moduleId], channelId, clkIntvCfg);
            /* Write back counter enable bits */
            PWM_REG_WRITE32_RBC(tempValue, tempAddr);
        } /* else not needed */
        /* #50 Write the overflow value and upload */
        coreHandlerPtr->counterXtrgOvfValue[xtrgIndex][channelId] = period;
        /* Write ovf value */
        counterValue = (counterValue / Pwm_XtrgCntIntvList[clkIntvCfg]) - 1U;
        PWM_REG_WRITE32_RBC((uint32)counterValue, coreHandlerPtr->baseAddr[moduleId]
                + PWM_IP_XTRG_CNT_OVF_N(channelId));
        /* Force reload */
        tempAddr = coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CNT_OVF_N(channelId);
        tempValue = REG_READ32(tempAddr) | (1UL << PWM_IP_XTRG_CNT_EN_OFFSET);
        REG_WRITE32(tempValue, tempAddr);
    }

    return errorId;
}

#define PWM_STOP_SEC_CODE
#include "Pwm_MemMap.h"

#define PWM_START_SEC_CODE_FAST
#include "Pwm_MemMap.h"

/** *****************************************************************************************************
 * \brief Check Pwm IRQ enable and status is set not not.
 *
 * \verbatim
 * Syntax             : static boolean Pwm_Ip_Xtrg_IrqCheck(
 *                          uint32 base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base    - Xtrg-Pwm controller baseAddress.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : TRUE    - IRQ enable and status is set.
 *                      FALSE   - IRQ enable and status is not set.
 *
 * Description        : Check Pwm IRQ enable and status is set not not.
 *
 * \endverbatim
 * Traceability       : SW_SM004
 *******************************************************************************************************/
static boolean Pwm_Ip_Xtrg_IrqCheck(uint32 base)
{
    /* ----- Local Variables ---------------------------------------------- */
    boolean retVal = (boolean)FALSE;
    uint32 intStatus;
    uint32 intEnable;
    uint32 intSignal;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Read out the IRQ enable and status */
    intStatus = REG_READ32(base + PWM_IP_XTRG_OVF_INT_STA_REG);
    intEnable = REG_READ32(base + PWM_IP_XTRG_OVF_INT_STA_EN_REG);
    intSignal = REG_READ32(base + PWM_IP_XTRG_OVF_INT_SIG_EN_REG);

    /* #20 Check the IRQ enable and status */
    if (0UL != (intStatus & intEnable & intSignal))
    {
        retVal = (boolean)TRUE;
    } /* else not needed */

    return retVal;
}

#define PWM_STOP_SEC_CODE_FAST
#include "Pwm_MemMap.h"

#define PWM_START_SEC_CODE
#include "Pwm_MemMap.h"

/** *****************************************************************************************************
 * \brief Enable or disable Xtrg-Pwm interrupt status and signal.
 *
 * \verbatim
 * Syntax             : static void Pwm_Ip_XtrgSetStaSigInt(
 *                          uint32 base,
 *                          uint32 sta,
 *                          uint32 sig,
 *                          boolean enable)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base    - Xtrg-Pwm controller baseAddress.
 *                      sta     - PWM interrupt status bits.
 *                      sig     - PWM interrupt signal bit.
 *                      enable  - TRUE: enable, FALSE: disable
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Enable or disable Xtrg-Pwm interrupt status and signal.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_026
 *******************************************************************************************************/
static void Pwm_Ip_XtrgSetStaSigInt(uint32 base, uint32 sta, uint32 sig, boolean enable)
{
    /* ----- Local Variables ---------------------------------------------- */
    uint32 enSta;

    /* ----- Implementation ----------------------------------------------- */
    if ((boolean)TRUE == enable)
    {
        SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_00();
        /* #10 Read out interrupt status enable register */
        enSta = REG_READ32(base + PWM_IP_XTRG_OVF_INT_STA_EN_REG);
        /* #20 Write interrupt status enable register */
        PWM_REG_WRITE32_RBC(enSta | sta, base + PWM_IP_XTRG_OVF_INT_STA_EN_REG);
        /* #30 Read out interrupt signal enable register */
        enSta = REG_READ32(base + PWM_IP_XTRG_OVF_INT_SIG_EN_REG);
        /* #40 Write interrupt signal enable register */
        PWM_REG_WRITE32_RBC(enSta | sig, base + PWM_IP_XTRG_OVF_INT_SIG_EN_REG);
        SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_00();
    }
    else
    {
        SchM_Enter_Pwm_PWM_EXCLUSIVE_AREA_00();
        /* #50 Read out interrupt status enable register */
        enSta = REG_READ32(base + PWM_IP_XTRG_OVF_INT_STA_EN_REG);
        /* #60 Write interrupt status enable register */
        PWM_REG_WRITE32_RBC(enSta & (~sta), base + PWM_IP_XTRG_OVF_INT_STA_EN_REG);
        /* #70 Read out interrupt signal enable register */
        enSta = REG_READ32(base + PWM_IP_XTRG_OVF_INT_SIG_EN_REG);
        /* #80 Write interrupt signal enable register */
        PWM_REG_WRITE32_RBC(enSta & (~sig), base + PWM_IP_XTRG_OVF_INT_SIG_EN_REG);
        SchM_Exit_Pwm_PWM_EXCLUSIVE_AREA_00();
    }
}

/** *****************************************************************************************************
 * \brief Disable Pwm interrupt and clear interrupt status.
 *
 * \verbatim
 * Syntax             : static void Pwm_Ip_Xtrg_DisableAndClearInterrupt(
 *                          uint32 base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : base    - Xtrg-Pwm controller baseAddress.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Disable Pwm interrupt and clear interrupt status.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_026 SWSR_PWM_094
 *******************************************************************************************************/
static void Pwm_Ip_Xtrg_DisableAndClearInterrupt(uint32 base)
{
    /* ----- Implementation ----------------------------------------------- */
    /* #10 Disable Pwm interrupt*/
    Pwm_Ip_XtrgSetStaSigInt(base, PWM_IP_XTRG_INT_STA_EN, PWM_IP_XTRG_INT_SIG_EN, (boolean)FALSE);
    /* #20 Clear Pwm interrupt*/
    Pwm_Ip_Xtrg_ClearIntStatus(base);
}

/** *****************************************************************************************************
 * \brief Set Xtrg-Pwm duty cycle value.
 *
 * \verbatim
 * Syntax             : static Std_ReturnType Pwm_Ip_XtrgSetDuty(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr,
 *                          const Pwm_ModuleType curModule,
 *                          const uint8 channelId,
 *                          const uint16 duty)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      curModule       - Numeric identifier of the PWM hardware module.
 *                      channelId       - Numeric identifier of the PWM channel.
 *                      duty            - The duty of the PWM channel., Min=0x0000 Max=0x8000.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Set duty successful.
 *                      Others  - Set duty failed.
 *
 * Description        : Set Xtrg-Pwm duty cycle value.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_015 SWSR_PWM_026 SWSR_PWM_045
 *******************************************************************************************************/
static Std_ReturnType Pwm_Ip_XtrgSetDuty
(
    const Pwm_HandlerConfigType* coreHandlerPtr,
    const Pwm_ModuleType curModule,
    const uint8 channelId,
    const uint16 duty
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId = E_OK;
    uint32 moduleClk;
    uint64 cmpValue;
    uint16 dividerNum;
    Pwm_HrdControllerType moduleId;
    uint32 clkIntvReg;
    uint32 tempAddr;
    uint32 tempValue;
    uint32 xtrgIndex;
    const Pwm_HwModuleConfigType* moduleHwCfgPtr;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ConfigType* configPtr = coreHandlerPtr->configPtr;

    /* ----- Implementation ----------------------------------------------- */
    if (duty > PWM_IP_DUTY_100)
    {
        errorId = PWM_E_DUTYCYCLE_OUT_OF_RANGE;
    }
    else
    {
        /* #20 Get module id and module configure */
        moduleHwCfgPtr = &(configPtr->moduleHwCfgPtr[curModule]);
        moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
        moduleId = moduleCfgPtr->moduleId;
        xtrgIndex = (uint32)moduleId - (uint32)XTRG1_MODULE_INDEX;
        /* #30 Get module clock and divider number */
        dividerNum = moduleHwCfgPtr->dividerNum;
        moduleClk = moduleHwCfgPtr->moduleClk;
        clkIntvReg = Pwm_Ip_Xtrg_GetClkIntv(coreHandlerPtr->baseAddr[moduleId], channelId);
        /* #40 Calculated the compare value */
        cmpValue = (uint64)moduleClk / 1000000UL
                * coreHandlerPtr->counterXtrgOvfValue[xtrgIndex][channelId]
                * duty / ((uint64)dividerNum + 1U) / 1000UL / PWM_IP_DUTY_100;
        cmpValue = cmpValue / Pwm_XtrgCntIntvList[clkIntvReg];

        PwmHook_Pwm_Ip_XtrgSetDutyCmpOutOfRange();
        /* #50 Check compare value */
        if (cmpValue > PWM_IP_XTRG_COMPARE_VALUE_MAX)
        {
            errorId = PWM_E_COMPARE_OUT_OF_RANGE;
        }
        else
        {
            /* #60 Check compare value and upload */
            /* write cmp value */
            PWM_REG_WRITE32_RBC((uint32)cmpValue, coreHandlerPtr->baseAddr[moduleId]
                    + PWM_IP_XTRG_CMP_VALUE_N(channelId));
            /* Force reload */
            tempAddr = coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CMP_VALUE_N(channelId);
            tempValue = REG_READ32(tempAddr) | (1UL << PWM_IP_XTRG_CMP_EN_OFFSET);
            REG_WRITE32(tempValue, tempAddr);
        }
    }

    return errorId;
}

#if (STD_ON == PWM_DE_INIT_API)
/** *****************************************************************************************************
 * \brief Set Pwm output de-initialized state.
 *
 * \verbatim
 * Syntax             : static Std_ReturnType Pwm_Ip_Xtrg_SetOutputDeinitState(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr,
 *                          Pwm_ModuleType curModule,
 *                          uint8 channelId,
 *                          const Pwm_OutputStateType idleStatus)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      curModule       - Numeric identifier of the PWM hardware module.
 *                      channelId       - Numeric identifier of the PWM channel.
 *                      idleStatus      - Compare output state.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Set Pwm output de-initialized state successful.
 *                      Others  - Set Pwm output de-initialized state failed.
 *
 * Description        : Set Pwm output de-initialized state.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_026 SWSR_PWM_094
 *******************************************************************************************************/
static Std_ReturnType Pwm_Ip_Xtrg_SetOutputDeinitState
(
    const Pwm_HandlerConfigType* coreHandlerPtr,
    Pwm_ModuleType curModule,
    uint8 channelId,
    const Pwm_OutputStateType idleStatus
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Set output state */
    if (PWM_HIGH == idleStatus)
    {
        /* Set duty value */
        errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId, PWM_IP_DUTY_0);
    }
    else
    {
        /* Set duty value */
        errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId, PWM_IP_DUTY_100);
    }

    return errorId;
}
#endif /** #if (STD_ON == PWM_DE_INIT_API) */

/** *****************************************************************************************************
 * \brief Set Pwm channel duty initialized configure.
 *
 * \verbatim
 * Syntax             : static Std_ReturnType Pwm_Ip_XtrgSetDutyInitConfig(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr,
 *                          const Pwm_ModuleType curModule,
 *                          uint8 curChannel,
 *                          const Pwm_ChannelGroupType* channelGroupCfgPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr      - Pwm handler configutations.
 *                      curModule           - Numeric identifier of the PWM hardware module.
 *                      curChannel          - Numeric identifier of the PWM hardware channel.
 *                      channelGroupCfgPtr  - Point to Pwm channel group configure.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Set Pwm channel duty initialized configure successful.
 *                      Others  - Set Pwm channel duty initialized configure failed.
 *
 * Description        : Set Pwm channel duty initialized configure.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_026 SWSR_PWM_094
 *******************************************************************************************************/
static Std_ReturnType Pwm_Ip_XtrgSetDutyInitConfig
(
    const Pwm_HandlerConfigType* coreHandlerPtr,
    const Pwm_ModuleType curModule,
    uint8 curChannel,
    const Pwm_ChannelGroupType* channelGroupCfgPtr
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId;
    uint16 dutyCycle;
    Pwm_OutputStateType polarity;
    uint8 channelId;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Get channel id, 0ty cycle and polarity */
    channelId = channelGroupCfgPtr->channelGroup[curChannel].channelId;
    dutyCycle = channelGroupCfgPtr->channelGroup[curChannel].subChannelGroup[0].dutyCycle;
    polarity = channelGroupCfgPtr->channelGroup[curChannel].subChannelGroup[0].polarity;

    /* #30 polarity inverse if need */
    if (PWM_HIGH == polarity)
    {
        dutyCycle = PWM_IP_DUTY_100 - dutyCycle;
    } /* else not needed */

    /* #40  Set duty */
    errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId, dutyCycle);

    return errorId;
}

/** *****************************************************************************************************
 * \brief Xtrg-Pwm IP initialization.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Pwm_Ip_XtrgInit(
 *                          Pwm_HandlerConfigType *coreHandlerPtr,
 *                          const Pwm_ConfigType* configPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      configPtr       - Pointer to Pwm configuration set.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Pwm IP initialization successful.
 *                      Others  - Pwm IP initialization failed.
 *
 * Description        : Xtrg-Pwm IP initialization.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_025 SWSR_PWM_026 SWSR_PWM_027 SWSR_PWM_028 SWSR_PWM_029 SWSR_PWM_030
 *                      SWSR_PWM_093 SWSR_PWM_094
 *******************************************************************************************************/
Std_ReturnType Pwm_Ip_XtrgInit
(
    Pwm_HandlerConfigType *coreHandlerPtr,
    const Pwm_ConfigType* configPtr
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId = E_OK;
    Pwm_HrdControllerType moduleId;
    Pwm_ModuleType moduleNum;
    Pwm_ChannelType channelNum;
    Pwm_ModuleType curModule;
    uint8 curChannel;
    uint8 channelId;
    uint32 ioMuxSel;
    uint32 tempAddr;
    uint32 tempValue;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;
    /* #10 Get core id */
    uint8 coreId = Pwm_Ip_GetCoreID();

    /* ----- Implementation ----------------------------------------------- */
    /* #20 Get module total number */
    moduleNum = configPtr->moduleNum;
    /* Loop all moudles */
    for (curModule = ((uint8)0U); curModule < moduleNum;  curModule++)
    {
        /* Get module configure pointer */
        moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
        /* Check the assign core id */
        if (coreId != moduleCfgPtr->coreId)
        {
            /* core id not match, continue */
            continue;
        } /* else not needed */

        /* Get channel configure pointer and module id */
        channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
        moduleId = moduleCfgPtr->moduleId;

        /* EPWM/ETIMER module */
        if ((XTRG1_MODULE_INDEX != moduleId) && (XTRG2_MODULE_INDEX != moduleId))
        {
            /* module type match, continue */
            continue;
        } /* else not needed */

        /* #30 Disable and clear interrupt first */
        Pwm_Ip_Xtrg_DisableAndClearInterrupt(coreHandlerPtr->baseAddr[moduleId]);

        /* Pwm module clock gate enable */
        PWM_REG_WRITE32_RBC(PWM_IP_XTRG_CLK_GT_EN,
                (coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CFG_REG));

        /* Pwm software reset set */
        tempAddr = coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CFG_REG;
        tempValue = REG_READ32(tempAddr) | (PWM_IP_XTRG_SW_RST_EN << PWM_IP_XTRG_SW_RST_OFFSET);
        PWM_REG_WRITE32_RBC(tempValue, tempAddr);

        /* Get channel total number */
        channelNum = moduleCfgPtr->channelNum;
        /* Loop all channels */
        for (curChannel = ((uint8)0U); curChannel < channelNum; curChannel++)
        {
            /* Get channel id and selected counter */
            channelId = channelGroupCfgPtr->channelGroup[curChannel].channelId;

            /* #50 Set epwm counter overflow */
            errorId = Pwm_Ip_XtrgSetOverflow(coreHandlerPtr, curModule, channelId,
                    moduleCfgPtr->countCfg[channelId + PWM_IP_XTRG_COUNTER_CFG_OFFSET].period);
            PwmHook_Pwm_Ip_XtrgInitSetOverflow();

            if (E_OK == errorId)
            {
                /* #60 Set Pwm channel duty initialized value. */
                errorId = Pwm_Ip_XtrgSetDutyInitConfig(coreHandlerPtr, curModule, curChannel,
                        channelGroupCfgPtr);
            } /* else not needed */

            if (E_OK != errorId)
            {
                break;
            } /* else not needed */

            /* #70 Xtrg-Pwm output I/O select and compare polarity */
            ioMuxSel = (uint32)channelGroupCfgPtr->channelGroup[curChannel].xtrgPwmIoMuxSel;
            /* Read out output I/O select */
            tempValue = REG_READ32(coreHandlerPtr->baseAddr[moduleId]
                    + PWM_IP_XTRG_CH_CFG_N(channelId));
            tempValue = tempValue & (~(PWM_IP_XTRG_IO_MUX_SEL_MASK <<
                    PWM_IP_XTRG_IO_MUX_SEL_OFFSET));
            tempValue |= (ioMuxSel << PWM_IP_XTRG_IO_MUX_SEL_OFFSET);
            tempValue |= PWM_IP_XTRG_CMP_POL_EN;
            /* Write output I/O select and compare polarity */
            PWM_REG_WRITE32_RBC(tempValue, (coreHandlerPtr->baseAddr[moduleId]
                    + PWM_IP_XTRG_CH_CFG_N(channelId)));

            /* #90 Enabled Xtrg-Pwm counter */
            tempAddr = coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CNT_EN_REG;
            tempValue = REG_READ32(tempAddr) | PWM_IP_XTRG_CNT_EN_CH(channelId);
            PWM_REG_WRITE32_RBC(tempValue, tempAddr);
        }

        /* Pwm software reset release */
        tempAddr = coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CFG_REG;
        tempValue = REG_READ32(tempAddr) & (~(PWM_IP_XTRG_SW_RST_EN << PWM_IP_XTRG_SW_RST_OFFSET));
        PWM_REG_WRITE32_RBC(tempValue, tempAddr);
    }

    return errorId;
}

#if (STD_ON == PWM_DE_INIT_API)
/** *****************************************************************************************************
 * \brief Xtrg-Pwm IP de-initialization.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Pwm_Ip_XtrgDeinit(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Pwm IP de-initialization successful.
 *                      Others  - Pwm IP de-initialization failed.
 *
 * Description        : Xtrg-Pwm IP de-initialization.
 *                      This function is available if the PWM_DE_INIT_API is set STD_ON.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_036 SWSR_PWM_037 SWSR_PWM_038 SWSR_PWM_094
 *******************************************************************************************************/
Std_ReturnType Pwm_Ip_XtrgDeinit(const Pwm_HandlerConfigType* coreHandlerPtr)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId = E_OK;
    Pwm_HrdControllerType moduleId;
    Pwm_ModuleType moduleNum;
    Pwm_ModuleType curModule;
    Pwm_ChannelType channelNum;
    Pwm_ChannelType curChannel;
    uint8 channelId;
    Pwm_OutputStateType idleStatus;
    /* #10 Get core id */
    uint8 coreId = Pwm_Ip_GetCoreID();
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;
    const Pwm_ConfigType* configPtr = coreHandlerPtr->configPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* Get module total number */
    moduleNum = configPtr->moduleNum;
    /* Loop all moudles */
    for (curModule = ((uint8)0U); curModule < moduleNum; curModule++)
    {
        /* #20 Get module configure pointer */
        moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
        /* Check the assign core id */
        if (coreId != moduleCfgPtr->coreId)
        {
            /* core id not match, continue */
            continue;
        } /* else not needed */

        /* 30 Get channel configure pointer, module id and channel number */
        channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
        moduleId = moduleCfgPtr->moduleId;
        channelNum = moduleCfgPtr->channelNum;

        /* EPWM/ETIMER module */
        if ((XTRG1_MODULE_INDEX != moduleId) && (XTRG2_MODULE_INDEX != moduleId))
        {
            /* module type match, continue */
            continue;
        } /* else not needed */

        /* Loop all channels */
        for (curChannel = ((uint8)0U); curChannel < channelNum; curChannel++)
        {
            /* 40 Get channel id */
            channelId = channelGroupCfgPtr->channelGroup[curChannel].channelId;
            idleStatus
                = channelGroupCfgPtr->channelGroup[curChannel].subChannelGroup[0].idleStatus;
            /* #50 Set output deinit state */
            errorId = Pwm_Ip_Xtrg_SetOutputDeinitState(coreHandlerPtr, curModule, channelId,
                    idleStatus);
            PwmHook_Pwm_Ip_XtrgSetOutputDeinitState();

            if (E_OK != errorId)
            {
                break;
            } /* else not needed */
        }

        /* #60 Disable interrupt and clear interrupt status */
        Pwm_Ip_Xtrg_DisableAndClearInterrupt(coreHandlerPtr->baseAddr[moduleId]);


        if (E_OK != errorId)
        {
            /* Error during de-initialization, break */
            break;
        } /* else not needed */
    }

    return errorId;
}
#endif /** #if (STD_ON == PWM_DE_INIT_API) */

#if (STD_ON == PWM_SET_DUTY_CYCLE_API)
/** *****************************************************************************************************
 * \brief Set the duty cycle of the Xtrg-Pwm channel.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Pwm_Ip_XtrgSetDutyCycle(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr,
 *                          Pwm_ChannelType channelNumber,
 *                          uint16 dutyCycle)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      channelNumber   - Numeric identifier of the PWM channel.
 *                      dutyCycle       - The duty of the PWM channel., Min=0x0000 Max=0x8000.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Set duty cycle successful.
 *                      Others  - Set duty cycle failed.
 *
 * Description        : Set the duty cycle of the Xtrg-Pwm channel.
 *                      This function is available if the PWM_SET_DUTY_CYCLE_API is set STD_ON.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007 SWSR_PWM_015 SWSR_PWM_042 SWSR_PWM_043 SWSR_PWM_044
 *                      SWSR_PWM_045 SWSR_PWM_094
 *******************************************************************************************************/
Std_ReturnType Pwm_Ip_XtrgSetDutyCycle
(
    const Pwm_HandlerConfigType* coreHandlerPtr,
    Pwm_ChannelType channelNumber,
    uint16 dutyCycle
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId;
    Pwm_ModuleType curModule = 0x0U;
    Pwm_ChannelType curChannel = 0x0U;
    Pwm_OutputStateType polarity;
    uint8 channelId;
    uint16 dutyValue = dutyCycle;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;
    const Pwm_ConfigType* configPtr = coreHandlerPtr->configPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Get right moduleid and channel */
    Pwm_Ip_XtrgGetHardwareChannel(channelNumber, &curModule, &curChannel);
    /* #20 Get module configure point, cahnnel configure point, polarity, channel id, counter */
    moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
    channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
    polarity = channelGroupCfgPtr->channelGroup[curChannel].subChannelGroup[0].polarity;
    channelId = channelGroupCfgPtr->channelGroup[curChannel].channelId;

    /* #30 polarity inverse if need */
    if (PWM_HIGH == polarity)
    {
        dutyValue = PWM_IP_DUTY_100 - dutyValue;
    } /* else not needed */

    PwmHook_Pwm_Ip_XtrgSetDutyCycleOutOfRange();
    /* Xtrg-Pwm module set duty */
    errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId, dutyValue);

    return errorId;
}
#endif /** #if (STD_ON == PWM_SET_DUTY_CYCLE_API) */

#if (STD_ON == PWM_SET_PERIOD_AND_DUTY_API)
/** *****************************************************************************************************
 * \brief Set the period and the duty cycle of the Xtrg-Pwm channel.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Pwm_Ip_XtrgSetPeriodAndDuty(
 *                          Pwm_HandlerConfigType* coreHandlerPtr,
 *                          Pwm_ChannelType channelNumber,
 *                          Pwm_PeriodType period,
 *                          uint16 dutyCycle)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      channelNumber   - Numeric identifier of the PWM channel.
 *                      period          - Period of the PWM signal.
 *                      dutyCycle       - The duty of the PWM channel., Min=0x0000 Max=0x8000.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Set period and the duty cycle successful.
 *                      Others  - Set period and the duty cycle failed.
 *
 * Description        : Set the period and the duty cycle of the Xtrg-Pwm channel.
 *                      This function is available if the PWM_SET_PERIOD_AND_DUTY_API is set STD_ON.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007 SWSR_PWM_015 SWSR_PWM_043 SWSR_PWM_044 SWSR_PWM_045
 *                      SWSR_PWM_050 SWSR_PWM_051 SWSR_PWM_056 SWSR_PWM_094
 *******************************************************************************************************/
Std_ReturnType Pwm_Ip_XtrgSetPeriodAndDuty
(
    Pwm_HandlerConfigType* coreHandlerPtr,
    Pwm_ChannelType channelNumber,
    Pwm_PeriodType period,
    uint16 dutyCycle
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId = E_OK;
    Pwm_ModuleType curModule = 0x0U;
    Pwm_ChannelType curChannel = 0x0U;
    Pwm_OutputStateType polarity;
    uint8 channelId;
    uint16 dutyValue = dutyCycle;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Get right moduleid and channel */
    Pwm_Ip_XtrgGetHardwareChannel(channelNumber, &curModule, &curChannel);
    /* #20 Get module configure point, cahnnel configure point, polarity, channel id, counter */
    moduleCfgPtr = &(coreHandlerPtr->configPtr->moduleCfgPtr[curModule]);
    channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
    channelId = channelGroupCfgPtr->channelGroup[curChannel].channelId;
    polarity = channelGroupCfgPtr->channelGroup[curChannel].subChannelGroup[0].polarity;

    /* #30 Check channel class */
    if (PWM_VARIABLE_PERIOD
            == moduleCfgPtr->countCfg[channelId + PWM_IP_XTRG_COUNTER_CFG_OFFSET].channelClass)
    {
        /* #40 Set duty cycle and period */
        if (period > 0U)
        {
            /* Set Xtrg-Pwm counter overflow */
            errorId = Pwm_Ip_XtrgSetOverflow(coreHandlerPtr, curModule, channelId, period);
            if (E_OK == errorId)
            {
                /* Polarity inverse if need */
                if (PWM_HIGH == polarity)
                {
                    dutyValue = PWM_IP_DUTY_100 - dutyValue;
                } /* else not needed */

                /* Xtrg-Pwm module set duty */
                errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId, dutyValue);
            } /* else not needed */
        }
        else
        {
            /* Polarity inverse if need */
            if (PWM_HIGH == polarity)
            {
                /* Xtrg-Pwm module set duty */
                errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId,
                        PWM_IP_DUTY_100);
            }
            else
            {
                /* Xtrg-Pwm module set duty */
                errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId,
                        PWM_IP_DUTY_0);
            }
        }
    } /* else not needed */

    return errorId;
}
#endif /** #if (STD_ON == PWM_SET_PERIOD_AND_DUTY_API) */

#if (STD_ON == PWM_SET_OUTPUT_TO_IDLE_API)
/** *****************************************************************************************************
 * \brief Set Xtrg-Pwm channel output status to idle.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Pwm_Ip_XtrgSetOutputToIdle(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr,
 *                          Pwm_ChannelType channelNumber)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
  *                     channelNumber   - Numeric identifier of the PWM channel.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Set PWM channel output status to idle successful.
 *                      Others  - Set PWM channel output status to idle failed.
 *
 * Description        : Set Xtrg-Pwm channel output status to idle.
 *                      This function is available if the PWM_SET_OUTPUT_TO_IDLE_API is set STD_ON.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007 SWSR_PWM_057 SWSR_PWM_094
 *******************************************************************************************************/
Std_ReturnType Pwm_Ip_XtrgSetOutputToIdle
(
    const Pwm_HandlerConfigType* coreHandlerPtr,
    Pwm_ChannelType channelNumber
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId;
    Pwm_ModuleType curModule = 0x0U;
    Pwm_ChannelType curChannel = 0x0U;
    uint8 channelId;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Get right moduleid and channel */
    Pwm_Ip_XtrgGetHardwareChannel(channelNumber, &curModule, &curChannel);
    /* #20 Get module configure point, cahnnel configure point, channel id, counter */
    moduleCfgPtr = &(coreHandlerPtr->configPtr->moduleCfgPtr[curModule]);
    channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
    channelId = channelGroupCfgPtr->channelGroup[curChannel].channelId;

    /* #30 Set channel output idle state */
    if (PWM_HIGH ==
        channelGroupCfgPtr->channelGroup[curChannel].subChannelGroup[0].idleStatus)
    {
        /* Xtrg-Pwm module set duty */
        errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId, PWM_IP_DUTY_0);
    }
    else
    {
        /* Xtrg-Pwm module set duty */
        errorId = Pwm_Ip_XtrgSetDuty(coreHandlerPtr, curModule, channelId, PWM_IP_DUTY_100);
    }

    return errorId;
}
#endif /** #if (STD_ON == PWM_SET_OUTPUT_TO_IDLE_API) */

#if (STD_ON == PWM_NOTIFICATION_SUPPORTED)
/** *****************************************************************************************************
 * \brief Disable notification of Xtrg-Pwm channel.
 *
 * \verbatim
 * Syntax             : void Pwm_Ip_XtrgDisableNotification(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr,
 *                          Pwm_ChannelType channelNumber)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      channelNumber   - Numeric identifier of the PWM channel.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Disable notification of Xtrg-Pwm channel.
 *                      This function is available if the PWM_NOTIFICATION_SUPPORTED is set STD_ON.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007 SWSR_PWM_080
 *******************************************************************************************************/
void Pwm_Ip_XtrgDisableNotification
(
    const Pwm_HandlerConfigType* coreHandlerPtr,
    Pwm_ChannelType channelNumber
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Pwm_ModuleType curModule = 0x0U;
    Pwm_ChannelType curChannel = 0x0U;
    Pwm_HrdControllerType moduleId;
    uint32 channelId;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Get right moduleid and channel */
    Pwm_Ip_XtrgGetHardwareChannel(channelNumber, &curModule, &curChannel);
    /* #20 Get module configure point, cahnnel configure point, module id, channel id, counter */
    moduleCfgPtr = &(coreHandlerPtr->configPtr->moduleCfgPtr[curModule]);
    moduleId = moduleCfgPtr->moduleId;
    channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
    channelId = (uint32)channelGroupCfgPtr->channelGroup[curChannel].channelId;

    /* #30 Xtrg-Pwm module disable interrupt */
    Pwm_Ip_XtrgSetStaSigInt(coreHandlerPtr->baseAddr[moduleId],
            PWM_IP_XTRG_INT_CNT_OVF_EN(channelId),
            PWM_IP_XTRG_INT_CNT_OVF_EN(channelId), (boolean)FALSE);
}
#endif /** #if (STD_ON == PWM_NOTIFICATION_SUPPORTED) */

#if (STD_ON == PWM_NOTIFICATION_SUPPORTED)
/** *****************************************************************************************************
 * \brief Enable notification of Xtrg-Pwm channel.
 *
 * \verbatim
 * Syntax             : void Pwm_Ip_XtrgEnableNotification(
 *                          const Pwm_HandlerConfigType* coreHandlerPtr,
 *                          Pwm_ChannelType channelNumber,
 *                          Pwm_EdgeNotificationType notification)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *                      channelNumber   - Numeric identifier of the PWM channel.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Enable notification of Xtrg-Pwm channel.
 *                      This function is available if the PWM_NOTIFICATION_SUPPORTED is set STD_ON.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007 SWSR_PWM_073 SWSR_PWM_074 SWSR_PWM_080
 *******************************************************************************************************/
void Pwm_Ip_XtrgEnableNotification
(
    const Pwm_HandlerConfigType* coreHandlerPtr,
    Pwm_ChannelType channelNumber,
    Pwm_EdgeNotificationType notification
)
{
    /* ----- Local Variables ---------------------------------------------- */
    Pwm_ModuleType curModule = 0x0U;
    Pwm_ChannelType curChannel = 0x0U;
    Pwm_HrdControllerType moduleId;
    uint32 channelId;
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* #10 Get right moduleid and channel */
    Pwm_Ip_XtrgGetHardwareChannel(channelNumber, &curModule, &curChannel);
    /* #20 Get module configure point, cahnnel configure point, module id, counter */
    moduleCfgPtr = &(coreHandlerPtr->configPtr->moduleCfgPtr[curModule]);
    moduleId = moduleCfgPtr->moduleId;
    channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;

    /* Notification only support falling edge */
    if (PWM_FALLING_EDGE == notification)
    {
        channelId = (uint32)channelGroupCfgPtr->channelGroup[curChannel].channelId;
        /* Xtrg-Pwm module enable interrupt */
        /* #30 Xtrg-Pwm module enable interrupt */
        Pwm_Ip_XtrgSetStaSigInt(coreHandlerPtr->baseAddr[moduleId],
                PWM_IP_XTRG_INT_CNT_OVF_EN(channelId),
                PWM_IP_XTRG_INT_CNT_OVF_EN(channelId), (boolean)TRUE);

    } /* else not needed */
}
#endif /** #if (STD_ON == PWM_NOTIFICATION_SUPPORTED) */

#if defined(LOWPOWER_SUPPORT_SUSPEND_RESUME)
/** *****************************************************************************************************
 * \brief Xtrg-Pwm IP suspend.
 *
 * \verbatim
 * Syntax             : Std_ReturnType Pwm_Ip_XtrgSuspend(
 *                          Pwm_HandlerConfigType* coreHandlerPtr)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : coreHandlerPtr  - Pwm handler configutations.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : E_OK    - Xtrg-Pwm IP suspend successful.
 *                      Others  - Xtrg-Pwm IP suspend failed.
 *
 * Description        : Suspend the Xtrg-Pwm IP, just only used for lowpower.
 *
 * \endverbatim
 * Traceability       : SWSR_GENERAL_22
 *******************************************************************************************************/
Std_ReturnType Pwm_Ip_XtrgSuspend(Pwm_HandlerConfigType* coreHandlerPtr)
{
    /* ----- Local Variables ---------------------------------------------- */
    Std_ReturnType errorId = E_OK;
    Pwm_HrdControllerType moduleId;
    Pwm_ModuleType moduleNum;
    Pwm_ModuleType curModule;
    Pwm_ChannelType channelNum;
    Pwm_ChannelType curChannel;
    uint8 channelId;
    uint32 tempAddr;
    uint32 tempValue;
    /* #10 Get core id */
    uint8 coreId = Pwm_Ip_GetCoreID();
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ChannelGroupType* channelGroupCfgPtr;
    const Pwm_ConfigType* configPtr = coreHandlerPtr->configPtr;

    /* ----- Implementation ----------------------------------------------- */
    /* Get module total number */
    moduleNum = configPtr->moduleNum;
    /* Loop all moudles */
    for (curModule = ((uint8)0U); curModule < moduleNum; curModule++)
    {
        /* #20 Get module configure pointer */
        moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
        /* Check the assign core id */
        if (coreId != moduleCfgPtr->coreId)
        {
            /* core id not match, continue */
            continue;
        } /* else not needed */

        /* 30 Get channel configure pointer, module id and channel number */
        channelGroupCfgPtr = moduleCfgPtr->channelGroupCfgPtr;
        moduleId = moduleCfgPtr->moduleId;
        channelNum = moduleCfgPtr->channelNum;

        /* EPWM/ETIMER module */
        if ((XTRG1_MODULE_INDEX != moduleId) && (XTRG2_MODULE_INDEX != moduleId))
        {
            /* module type match, continue */
            continue;
        } /* else not needed */

        /* Loop all channels */
        for (curChannel = ((uint8)0U); curChannel < channelNum; curChannel++)
        {
            /* #40 Disable Xtrg-Pwm counter */
            channelId = channelGroupCfgPtr->channelGroup[curChannel].channelId;
            tempAddr = coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CNT_EN_REG;
            tempValue = REG_READ32(tempAddr) & (~PWM_IP_XTRG_CNT_EN_CH(channelId));
            PWM_REG_WRITE32_RBC(tempValue, tempAddr);
        }

        /* #50 Disable interrupt and clear interrupt status */
        Pwm_Ip_Xtrg_DisableAndClearInterrupt(coreHandlerPtr->baseAddr[moduleId]);

        /* #60 Pwm module clock gate disable */
        PWM_REG_WRITE32_RBC(PWM_IP_XTRG_CLK_GT_DIS,
                (coreHandlerPtr->baseAddr[moduleId] + PWM_IP_XTRG_CFG_REG));
    }

    return errorId;
}
#endif /* #if defined(LOWPOWER_SUPPORT_SUSPEND_RESUME) */

#define PWM_STOP_SEC_CODE
#include "Pwm_MemMap.h"

#define PWM_START_SEC_CODE_FAST
#include "Pwm_MemMap.h"

/** *****************************************************************************************************
 * \brief Xtrg-Pwm interrupt handler.
 *
 * \verbatim
 * Syntax             : void Pwm_Ip_XtrgIrq(
 *                          Pwm_XtrgControllerIrqType xtrgController)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Reentrant
 *
 * Parameters (in)    : xtrgController - Pwm controller irq index: XTRG1_PWM_MODULE_IRQ_INDEX,
 *                                       XTRG2_PWM_MODULE_IRQ_INDEX
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Xtrg-Pwm interrupt handler, clear irq status and call notification function.
 *
 * \endverbatim
 * Traceability       : SWSR_PWM_006 SWSR_PWM_007 SWSR_PWM_089 SW_SM003 SW_SM004
 *******************************************************************************************************/
void Pwm_Ip_XtrgIrq(Pwm_XtrgControllerIrqType xtrgController)
{
    /* ----- Local Variables ---------------------------------------------- */
    Pwm_ModuleType curModule;
    Pwm_ModuleType moduleNum;
    Pwm_HrdControllerType moduleId;
    boolean checkIrq = FALSE;
    uint32 xtrgIndex = (uint32)xtrgController;
    uint32 moduleBaseAddr;
    /* #10 Get core id and pwm handler */
    uint8 coreId = Pwm_Ip_GetCoreID();
    const Pwm_HandlerConfigType* coreHandlerPtr = Pwm_HandlerPtr[coreId];
    const Pwm_ModuleConfigType* moduleCfgPtr;
    const Pwm_ConfigType* configPtr = coreHandlerPtr->configPtr;

    /* ----- Implementation ----------------------------------------------- */
    PwmHookBegin_Pwm_Ip_XtrgIrq();
    /* #20 Check Pwm init state */
    moduleBaseAddr = Pwm_XtrgBaseAddr[xtrgIndex];
    if (PWM_STATE_INIT != coreHandlerPtr->globalState)
    {
        /* #30 Disable and clear pwm interrupt */
        Pwm_Ip_Xtrg_DisableAndClearInterrupt(moduleBaseAddr);
    }
    else
    {
        /* Get module total number */
        moduleNum = configPtr->moduleNum;
        /* Loop all moudles */
        for (curModule = ((uint8)0U);  curModule < moduleNum;  curModule++)
        {
            /* #40 Get module configure pointer and module id */
            moduleCfgPtr = &(configPtr->moduleCfgPtr[curModule]);
            moduleId = moduleCfgPtr->moduleId;
            /* #50 Accord module base address find the right Xtrg-Pwm module */
            if (moduleBaseAddr == coreHandlerPtr->baseAddr[moduleId])
            {
                /* #60 Check the IRQ enable and status is set or not */
                checkIrq = Pwm_Ip_Xtrg_IrqCheck(coreHandlerPtr->baseAddr[moduleId]);
                break;
            } /* else not needed */
        }

        /* #70 Clear interrupt status */
        Pwm_Ip_Xtrg_ClearIntStatus(moduleBaseAddr);

        /* #80 Check notification in module configure point */
        if ((boolean)TRUE == checkIrq)
        {
            if (NULL_PTR != moduleCfgPtr->notificationPtr)
            {
                /* #90 Call notification callback function */
                moduleCfgPtr->notificationPtr();
            } /* else not needed */
        } /* else not needed */
    } /* else not needed */
    PwmHookEnd_Pwm_Ip_XtrgIrq();
}

#define PWM_STOP_SEC_CODE_FAST
#include "Pwm_MemMap.h"

#ifdef __cplusplus
}
#endif
/* End of file */
